// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package bytes

// 用于封送数据的简单字节缓冲区。

import (
	"errors"
	"io"
	"unicode/utf8"
)

// smallBufferSize是初始分配的最小容量。
const smallBufferSize = 64

// 缓冲区是一种大小可变的字节缓冲区，具有读写方法。
// 缓冲区的零值是一个空缓冲区，可以使用。
type Buffer struct {
	buf      []byte // 内容是字节buf[off:len（buf）]
	off      int    // 读取at&buf[off]，写入at&buf[len（buf）]
	lastRead readOp // 最后一次读取操作，以便未读*可以正常工作。
}

// readOp常量描述了在缓冲区中对
// 执行的最后一个操作，因此UnderRune和UnderByte可以检查
// 是否使用无效。opReadRuneX常量的选择应确保
// 转换为int，它们对应于读取的符文大小。
type readOp int8

// 不要使用iota进行这些操作，因为这些值需要与
// 名称和注释相对应，这在显式显示时更容易看到。
const (
	opRead      readOp = -1 // 任何其他读取操作。
	opInvalid   readOp = 0  // 非读取操作。
	opReadRune1 readOp = 1  // 读取大小为1的符文。
	opReadRune2 readOp = 2  // 阅读2号符文。wen jian defg
	opReadRune4 readOp = 4  // 阅读大小为4的符文。
)

// 如果无法分配内存将数据存储在缓冲区中，则会将ErrTooLarge传递给panic。
var ErrTooLarge = errors.New("bytes.Buffer: too large")
var errNegativeRead = errors.New("bytes.Buffer: reader returned negative count from Read")

const maxInt = int(^uint(0) >> 1)

// Bytes返回一个长度为b的片段。Len（）保存缓冲区的未读部分。
// 该片仅在下次修改缓冲区之前有效（即，
// 仅在下次调用读、写、重置或截断等方法之前有效）。
// 至少在下一次修改缓冲区之前，切片会为缓冲区内容添加别名，因此切片的即时更改将影响未来读取的结果。
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }

// String以字符串形式返回缓冲区未读部分的内容。如果缓冲区是nil指针，则返回“<nil>”。
// 
// 要更有效地构建字符串，请参阅字符串。生成器类型。
func (b *Buffer) String() string {
	if b == nil {
		// 特例，用于调试。
		return "<nil>"
	}
	return string(b.buf[b.off:])
}

// empty报告缓冲区的未读部分是否为空。
func (b *Buffer) empty() bool { return len(b.buf) <= b.off }

// Len返回缓冲区未读部分的字节数；
// b.Len（）==Len（b.Bytes（））。
func (b *Buffer) Len() int { return len(b.buf) - b.off }

// Cap返回缓冲区底层字节片的容量，即分配给缓冲区数据的总空间。
func (b *Buffer) Cap() int { return cap(b.buf) }

// Truncate丢弃缓冲区中除前n个未读字节外的所有字节
// 但继续使用相同的已分配存储。
// 如果n为负或大于缓冲区的长度，则会出现恐慌。
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		b.Reset()
		return
	}
	b.lastRead = opInvalid
	if n < 0 || n > b.Len() {
		panic("bytes.Buffer: truncation out of range")
	}
	b.buf = b.buf[:b.off+n]
}

// 重置将缓冲区重置为空，
// 但它保留了底层存储以供将来写入使用。
// 重置与截断（0）相同。
func (b *Buffer) Reset() {
	b.buf = b.buf[:0]
	b.off = 0
	b.lastRead = opInvalid
}

// tryGrowByReslice是一个可内联版本的grow，用于快速情况，其中
// 内部缓冲区只需要重新许可。
// 返回应该写入字节的索引以及是否成功。
func (b *Buffer) tryGrowByReslice(n int) (int, bool) {
	if l := len(b.buf); n <= cap(b.buf)-l {
		b.buf = b.buf[:l+n]
		return l, true
	}
	return 0, false
}

// grow增加缓冲区，以保证多容纳n个字节。
// 返回应该写入字节的索引。
// 如果缓冲区无法增长，它将因错误而恐慌。
func (b *Buffer) grow(n int) int {
	m := b.Len()
	// 如果缓冲区为空，请重置以恢复空间。
	if m == 0 && b.off != 0 {
		b.Reset()
	}
	// 试着通过重新切片来生长。
	if i, ok := b.tryGrowByReslice(n); ok {
		return i
	}
	if b.buf == nil && n <= smallBufferSize {
		b.buf = make([]byte, n, smallBufferSize)
		return 0
	}
	c := cap(b.buf)
	if n <= c/2-m {
		// 我们可以向下滑动，而不是分配一个新的
		// 切片。我们只需要m+n<=c来滑动，但是我们让容量增加了两倍，这样我们就不用把所有的时间都花在复制上了。
		copy(b.buf, b.buf[b.off:])
	} else if c > maxInt-c-n {
		panic(ErrTooLarge)
	} else {
		// 任何地方都没有足够的空间，我们需要分配。
		buf := makeSlice(2*c + n)
		copy(buf, b.buf[b.off:])
		b.buf = buf
	}
	// 恢复b.off和len（b.buf）。
	b.off = 0
	b.buf = b.buf[:m+n]
	return m
}

// Grow增加缓冲区的容量，如有必要，以保证为
// 再增加n个字节的空间。在Grow（n）之后，至少可以将n个字节写入
// 缓冲区，而无需另一次分配。
// 如果n为负，Grow将恐慌。
// 如果缓冲区无法增长，它将因错误而恐慌。
func (b *Buffer) Grow(n int) {
	if n < 0 {
		panic("bytes.Buffer.Grow: negative count")
	}
	m := b.grow(n)
	b.buf = b.buf[:m]
}

// Write将p的内容追加到缓冲区，根据需要增加缓冲区。返回值n是p的长度；错误总是零。如果
// 缓冲区太大，写操作将因ErrTooLarge而死机。
func (b *Buffer) Write(p []byte) (n int, err error) {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(len(p))
	if !ok {
		m = b.grow(len(p))
	}
	return copy(b.buf[m:], p), nil
}

// WriteString将s的内容附加到缓冲区，根据需要增加缓冲区。返回值n是s的长度；错误总是零。如果
// 缓冲区太大，WriteString将因ErrTooLarge而死机。
func (b *Buffer) WriteString(s string) (n int, err error) {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(len(s))
	if !ok {
		m = b.grow(len(s))
	}
	return copy(b.buf[m:], s), nil
}

// MinRead是
// 缓冲区传递给读取调用的最小片大小。读读。只要缓冲区的最小读取字节数超过了
// 保存r内容所需的字节数，ReadFrom就不会增加
// 基础缓冲区。
const MinRead = 512

// ReadFrom从r读取数据，直到EOF，并将其附加到缓冲区，根据需要增加
// 缓冲区。返回值n是读取的字节数。任何
// 错误，io除外。读取过程中遇到的EOF也会返回。如果
// 缓冲区变得太大，ReadFrom将因ErrTooLarge而死机。
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
	b.lastRead = opInvalid
	for {
		i := b.grow(MinRead)
		b.buf = b.buf[:i]
		m, e := r.Read(b.buf[i:cap(b.buf)])
		if m < 0 {
			panic(errNegativeRead)
		}

		b.buf = b.buf[:i+m]
		n += int64(m)
		if e == io.EOF {
			return n, nil // e是EOF，因此显式返回nil 
		}
		if e != nil {
			return n, e
		}
	}
}

// makeSlice分配大小为n的片。如果分配失败，它将使用ErrTooLarge使
// 。
func makeSlice(n int) []byte {
	// 如果make失败，请给出一个已知错误。
	defer func() {
		if recover() != nil {
			panic(ErrTooLarge)
		}
	}()
	return make([]byte, n)
}

// writet将数据写入w，直到缓冲区耗尽或出现错误。
// 返回值n为写入的字节数；它总是适合
// int，但它是int64以匹配io。WriterTo接口。写入过程中遇到的任何错误
// 也将返回。
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
	b.lastRead = opInvalid
	if nBytes := b.Len(); nBytes > 0 {
		m, e := w.Write(b.buf[b.off:])
		if m > nBytes {
			panic("bytes.Buffer.WriteTo: invalid Write count")
		}
		b.off += m
		n = int64(m)
		if e != nil {
			return n, e
		}
		// 根据
		// io中的Write方法的定义，所有字节都应该被写入。写入程序
		if m != nBytes {
			return n, io.ErrShortWrite
		}
	}
	// 缓冲区现在为空；重置。
	b.Reset()
	return n, nil
}

// WriteByte将字节c追加到缓冲区，根据需要增加缓冲区。
// 返回的错误始终为零，但被包含以匹配bufio。作者
// WriteByte。如果缓冲区太大，WriteByte将因
// ErrTooLarge而死机。
func (b *Buffer) WriteByte(c byte) error {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(1)
	if !ok {
		m = b.grow(1)
	}
	b.buf[m] = c
	return nil
}

// WriteRune将Unicode代码点r的UTF-8编码附加到
// 缓冲区，返回其长度和一个错误，该错误始终为零，但包含
// 以匹配bufio。作家的笔迹。根据需要生长缓冲液；
// 如果它变得太大，WriterOne会因为ErrTooLarge而惊慌失措。
func (b *Buffer) WriteRune(r rune) (n int, err error) {
	// 比较as uint32以正确处理负面符文。
	if uint32(r) < utf8.RuneSelf {
		b.WriteByte(byte(r))
		return 1, nil
	}
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(utf8.UTFMax)
	if !ok {
		m = b.grow(utf8.UTFMax)
	}
	n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
	b.buf = b.buf[:m+n]
	return n, nil
}

// 读取从缓冲区读取下一个len（p）字节，或直到缓冲区
// 耗尽。返回值n是读取的字节数。如果
// 缓冲区没有要返回的数据，则err为io。EOF（除非len（p）为零）；
// 否则为零。
func (b *Buffer) Read(p []byte) (n int, err error) {
	b.lastRead = opInvalid
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		if len(p) == 0 {
			return 0, nil
		}
		return 0, io.EOF
	}
	n = copy(p, b.buf[b.off:])
	b.off += n
	if n > 0 {
		b.lastRead = opRead
	}
	return n, nil
}

// 下一步返回一个包含缓冲区中接下来n个字节的切片，
// 将缓冲区向前推进，就像字节是通过读取返回的一样。
// 如果缓冲区中的字节少于n，Next将返回整个缓冲区。
// 该片仅在下次调用读或写方法之前有效。
func (b *Buffer) Next(n int) []byte {
	b.lastRead = opInvalid
	m := b.Len()
	if n > m {
		n = m
	}
	data := b.buf[b.off : b.off+n]
	b.off += n
	if n > 0 {
		b.lastRead = opRead
	}
	return data
}

// ReadByte读取并返回缓冲区中的下一个字节。
// 如果没有可用字节，则返回错误io。EOF。
func (b *Buffer) ReadByte() (byte, error) {
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		return 0, io.EOF
	}
	c := b.buf[b.off]
	b.off++
	b.lastRead = opRead
	return c, nil
}

// ReadRune读取并返回缓冲区中下一个UTF-8编码的
// Unicode代码点。
// 如果没有可用字节，返回的错误是io。EOF。
// 如果字节是错误的UTF-8编码，它将消耗一个字节并返回U+FFFD，1。
func (b *Buffer) ReadRune() (r rune, size int, err error) {
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		return 0, 0, io.EOF
	}
	c := b.buf[b.off]
	if c < utf8.RuneSelf {
		b.off++
		b.lastRead = opReadRune1
		return rune(c), 1, nil
	}
	r, n := utf8.DecodeRune(b.buf[b.off:])
	b.off += n
	b.lastRead = readOp(n)
	return r, n, nil
}

// 未读符文未读读符文返回的最后一个符文。
// 如果缓冲区上最近的读写操作是
// 读符文不成功，UnreadRune将返回错误。（在这方面，
// 比UnreadByte更严格，它将从任何读取操作中读取最后一个字节
// 。）
func (b *Buffer) UnreadRune() error {
	if b.lastRead <= opInvalid {
		return errors.New("bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune")
	}
	if b.off >= int(b.lastRead) {
		b.off -= int(b.lastRead)
	}
	b.lastRead = opInvalid
	return nil
}

var errUnreadByte = errors.New("bytes.Buffer: UnreadByte: previous operation was not a successful read")

// 未读字节未读最近一次成功的
// 读取至少一个字节的读取操作返回的最后一个字节。如果自上次读取
// 之后发生写入，如果上次读取返回错误，或者如果读取零
// 字节，则UnreadByte返回错误。
func (b *Buffer) UnreadByte() error {
	if b.lastRead == opInvalid {
		return errUnreadByte
	}
	b.lastRead = opInvalid
	if b.off > 0 {
		b.off--
	}
	return nil
}

// 读取字节数，直到输入中第一次出现delim，
// 返回一个包含数据的片段，该片段最多包含分隔符。
// 如果ReadBytes在查找分隔符之前遇到错误，
// 它将返回在错误之前读取的数据以及错误本身（通常是io.EOF）。
// ReadBytes返回错误！=nil当且仅当返回的数据不以
// delim结尾时。
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
	slice, err := b.readSlice(delim)
	// 返回切片的副本。缓冲区的后备数组可能会被以后的调用覆盖。
	line = append(line, slice...)
	return line, err
}

// readSlice类似于ReadBytes，但返回对内部缓冲区数据的引用。
func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
	i := IndexByte(b.buf[b.off:], delim)
	end := b.off + i + 1
	if i < 0 {
		end = len(b.buf)
		err = io.EOF
	}
	line = b.buf[b.off:end]
	b.off = end
	b.lastRead = opRead
	return line, err
}

// ReadString一直读取，直到输入中第一次出现delim，
// 返回一个包含数据的字符串，该字符串包含分隔符。
// 如果ReadString在查找分隔符之前遇到错误，
// 它将返回在错误之前读取的数据以及错误本身（通常是io.EOF）。
// ReadString返回错误！=nil当且仅当返回的数据不以delim中的
// 结尾时。
func (b *Buffer) ReadString(delim byte) (line string, err error) {
	slice, err := b.readSlice(delim)
	return string(slice), err
}

// NewBuffer使用buf作为其初始内容创建并初始化一个新缓冲区。新的缓冲区拥有buf的所有权，
// 调用方在此调用后不应使用buf。NewBuffer旨在
// 准备一个缓冲区来读取现有数据。它还可以用于设置
// 用于写入的内部缓冲区的初始大小。为此，
// buf应该具有所需的容量，但长度为零。
// 
// 在大多数情况下，new（Buffer）（或仅声明一个缓冲区变量）足以初始化缓冲区。
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }

// NewBufferString使用字符串s作为其初始内容创建并初始化一个新缓冲区。其目的是准备一个缓冲区来读取现有的
// 字符串。
// 
// 在大多数情况下，new（Buffer）（或仅声明一个缓冲区变量）足以初始化缓冲区。
func NewBufferString(s string) *Buffer {
	return &Buffer{buf: []byte(s)}
}